﻿#region COPYRIGHT
//--------------------------------------------------------------------------------
// <copyright file="ContentReaderHelper.cs" company="starLiGHT Entertainment Studios">
//    Copyright (c) 2008, 2009, 2010, 2011
//       Roland Rosenkranz (Glatzemann@email.de)
// </copyright>
// <license>
//   This file is part of starLiGHT.Particles.
//
//   starLiGHT.Particles is free software: you can redistribute it and/or modify
//   it under the terms of the GNU Lesser General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   starLiGHT.Particles is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU Lesser General Public License for more details.
//
//   You should have received a copy of the GNU Lesser General Public License
//   along with starLiGHT.Particles. If not, see http://www.gnu.org/licenses/.
//    
//   ADDITIONAL (commercial) LICENSES for starLiGHT.Particles are available on request.
// </license>
// <version>
// **************[ starLiGHT.Engine SVN ]**********************
// * $Rev::                       $:  Revision of last commit *
// * $Author::                    $:  Author of last commit   *
// * $Date::                      $:  Date of last commit     *
// ************************************************************
// </version>
//--------------------------------------------------------------------------------
#endregion

namespace starLiGHT.ContentPipeline.ParticleSystem
{
    #region Using Statements
    using System;
    using System.Collections.Generic;
    using System.Text;
    using Microsoft.Xna.Framework.Content;
    using starLiGHT.ParticleSystem.Common;
    using starLiGHT.ParticleSystem.Initializer;
    using starLiGHT.ParticleSystem.Initializer.TwoD;
    using starLiGHT.ParticleSystem.Modifier;
    using starLiGHT.ParticleSystem.Modifier.twoD;
    using starLiGHT.ParticleSystem.PulseGenerators;
    using starLiGHT.ParticleSystem.twoD;
    #endregion

    public static class ContentReaderHelper
    {
        public static IRegion2D ContentReadRegion(ContentReader input)
        {
            IRegion2D region = null;

            string typeName = input.ReadString().ToLower();
            switch (typeName)
            {
                case "rectangleregion":
                    region = input.ReadObject<RectangleRegion>(new RectangleRegionReader());
                    break;
                case "pointregion":
                    region = input.ReadObject<PointRegion>(new PointRegionReader());
                    break;
                case "lineregion":
                    region = input.ReadObject<LineRegion>(new LineRegionReader());
                    break;
                case "discregion":
                    region = input.ReadObject<DiscRegion>(new DiscRegionReader());
                    break;
                case "discsectorregion":
                    region = input.ReadObject<DiscSectorRegion>(new DiscSectorRegionReader());
                    break;
            }

            return region;
        }

        public static IModifier ContentReadModifier(ContentReader input)
        {
            IModifier modifier = null;

            string typeName = input.ReadString().ToLower();
            switch (typeName)
            {
                case "gravity":
                    modifier = input.ReadObject<Gravity>(new GravityReader());
                    break;
                case "antigravity":
                    modifier = input.ReadObject<AntiGravity>(new AntiGravityReader());
                    break;
                case "age":
                    modifier = input.ReadObject<Age>(new AgeReader());
                    break;
                case "changecollisionradius":
                    modifier = input.ReadObject<ChangeCollisionRadius>(new ChangeCollisionRadiusReader());
                    break;
                case "fade":
                    modifier = input.ReadObject<Fade>(new FadeReader());
                    break;
                case "changemass":
                    modifier = input.ReadObject<ChangeMass>(new ChangeMassReader());
                    break;
                case "scale":
                    modifier = input.ReadObject<starLiGHT.ParticleSystem.Modifier.Scale>(new ScaleModifierReader());
                    break;
                case "targetscale":
                    modifier = input.ReadObject<starLiGHT.ParticleSystem.Modifier.TargetScale>(new TargetScaleModifierReader());
                    break;
                case "accelerate":
                    modifier = input.ReadObject<Accelerate>(new AccelerateModifierReader());
                    break;
                case "move":
                    modifier = input.ReadObject<Move>(new MoveModifierReader());
                    break;
                case "friction":
                    modifier = input.ReadObject<Friction>(new FrictionModifierReader());
                    break;
                case "rotationalfriction":
                    modifier = input.ReadObject<RotationalFriction>(new RotationalFrictionModifierReader());
                    break;
                case "lineardrag":
                    modifier = input.ReadObject<LinearDrag>(new LinearDragModifierReader());
                    break;
                case "quadraticdrag":
                    modifier = input.ReadObject<QuadraticDrag>(new QuadraticDragModifierReader());
                    break;
                case "rotationallineardrag":
                    modifier = input.ReadObject<RotationalLinearDrag>(new RotationalLinearDragModifierReader());
                    break;
                case "rotationalquadraticdrag":
                    modifier = input.ReadObject<RotationalQuadraticDrag>(new RotationalQuadraticDragModifierReader());
                    break;
                case "rotate":
                    modifier = input.ReadObject<Rotate>(new RotateModifierReader());
                    break;
                case "rotatetodirection":
                    modifier = input.ReadObject<RotateToDirection>(new RotateToDirectionModifierReader());
                    break;
                case "deathspeed":
                    modifier = input.ReadObject<DeathSpeed>(new DeathSpeedModifierReader());
                    break;
                case "randomdrift":
                    modifier = input.ReadObject<RandomDrift>(new RandomDriftModifierReader());
                    break;
                case "speedlimit":
                    modifier = input.ReadObject<SpeedLimit>(new SpeedLimitModifierReader());
                    break;
                case "targetvelocity":
                    modifier = input.ReadObject<TargetVelocity>(new TargetVelocityModifierReader());
                    break;
                case "targetrotatevelocity":
                    modifier = input.ReadObject<TargetRotateVelocity>(new TargetRotateVelocityModifierReader());
                    break;
                case "targetcolor":
                    modifier = input.ReadObject<TargetColor>(new TargetColorModifierReader());
                    break;
                case "changecolor":
                    modifier = input.ReadObject<ChangeColor>(new ChangeColorModifierReader());
                    break;
                case "boundingbox":
                    modifier = input.ReadObject<BoundingBox>(new BoundingBoxModifierReader());
                    break;
                case "scaleall":
                    modifier = input.ReadObject<starLiGHT.ParticleSystem.Modifier.twoD.ScaleAll>(new ScaleAllModifierReader());
                    break;
                case "jet":
                    modifier = input.ReadObject<Jet>(new JetModifierReader());
                    break;
                case "deathregion":
                    modifier = input.ReadObject<DeathRegion>(new DeathRegionModifierReader());
                    break;
                case "tweenposition":
                    modifier = input.ReadObject<TweenPosition>(new TweenPositionModifierReader());
                    break;
            }

            return modifier;
        }

        public static IPulseGenerator ContentReadPulseGenerator(ContentReader input)
        {
            IPulseGenerator pulse = null;

            string typeName = input.ReadString().ToLower();
            switch (typeName)
            {
                case "nullpulse":
                    pulse = input.ReadObject<NullPulse>(new NullPulseReader());
                    break;
                case "burst":
                    pulse = input.ReadObject<Burst>(new BurstReader());
                    break;
                case "pulse":
                    pulse = input.ReadObject<Pulse>(new PulseReader());
                    break;
                case "performanceadjusted":
                    pulse = input.ReadObject<PerformanceAdjusted>(new PerformanceAdjustedReader());
                    break;
                case "timeperiod":
                    pulse = input.ReadObject<TimePeriod>(new TimePeriodReader());
                    break;
                case "steady":
                    pulse = input.ReadObject<Steady>(new SteadyReader());
                    break;
                case "random":
                    pulse = input.ReadObject<starLiGHT.ParticleSystem.PulseGenerators.Random>(new RandomPulseReader());
                    break;
                case "sine":
                    pulse = input.ReadObject<starLiGHT.ParticleSystem.PulseGenerators.Sine>(new SineReader());
                    break;
            }
            
            return pulse;
        }

        public static Initializer ContentReadInitializer(ContentReader input)
        {
            Initializer ini = null;

            string typeName = input.ReadString().ToLower();
            switch (typeName)
            {
                case "alpha":
                    ini = input.ReadObject<Alpha>(new AlphaReader());
                    break;
                case "collisionradius":
                    ini = input.ReadObject<CollisionRadius>(new CollisionRadiusReader());
                    break;
                case "colorinitializer":
                    ini = input.ReadObject<ColorInitializer>(new ColorInitializerReader());
                    break;
                case "lifetime":
                    ini = input.ReadObject<Lifetime>(new LifetimeReader());
                    break;
                case "mass":
                    ini = input.ReadObject<Mass>(new MassReader());
                    break;
                case "scale":
                    ini = input.ReadObject<starLiGHT.ParticleSystem.Initializer.Scale>(new ScaleReader());
                    break;
                case "random":
                    ini = input.ReadObject<starLiGHT.ParticleSystem.Initializer.Random>(new RandomReader());
                    break;
                case "initializercollection":
                    ini = input.ReadObject<starLiGHT.ParticleSystem.Initializer.InitializerCollection>(new InitializerCollectionReader());
                    break;
                case "randomcolor":
                    ini = input.ReadObject<starLiGHT.ParticleSystem.Initializer.RandomColor>(new RandomColorReader());
                    break;
                case "randomscale":
                    ini = input.ReadObject<RandomScale>(new RandomScaleReader());
                    break;
                case "randomscaleall":
                    ini = input.ReadObject<RandomScaleAll>(new RandomScaleAllReader());
                    break;
                case "rotatevelocity":
                    ini = input.ReadObject<RotateVelocity>(new RotateVelocityReader());
                    break;
                case "rotation":
                    ini = input.ReadObject<Rotation>(new RotationReader());
                    break;
                case "rotationabsolute":
                    ini = input.ReadObject<RotationAbsolute>(new RotationAbsoluteReader());
                    break;
                case "scaleall":
                    ini = input.ReadObject<starLiGHT.ParticleSystem.Initializer.TwoD.ScaleAll>(new ScaleAllReader());
                    break;
                case "textureinitializer":
                    ini = input.ReadObject<TextureInitializer>(new TextureInitializerReader());
                    break;
                case "randomtexture":
                    ini = input.ReadObject<RandomTexture>(new RandomTextureInitializerReader());
                    break;
                case "position":
                    ini = input.ReadObject<Position>(new PositionInitializerReader());
                    break;
                case "positionabsolute":
                    ini = input.ReadObject<PositionAbsolute>(new PositionAbsoluteInitializerReader());
                    break;
                case "velocity":
                    ini = input.ReadObject<Velocity>(new VelocityInitializerReader());
                    break;
            }

            return ini;
        }

        public static Func<float, float, float, float, float> getEasingFunc(string name)
        {
#if WINDOWS
            switch (name.ToLowerInvariant())
#else
            switch (name.ToLower())
#endif
            {
                case "linearnone":
                    return new Func<float, float, float, float, float>(Linear.easeNone);
                case "linearin":
                    return new Func<float, float, float, float, float>(Linear.easeIn);
                case "linearout":
                    return new Func<float, float, float, float, float>(Linear.easeOut);
                case "linearinout":
                    return new Func<float, float, float, float, float>(Linear.easeInOut);
                case "backin":
                    return new Func<float, float, float, float, float>(Back.easeIn);
                case "backout":
                    return new Func<float, float, float, float, float>(Back.easeOut);
                case "backinout":
                    return new Func<float, float, float, float, float>(Back.easeInOut);
                case "bouncein":
                    return new Func<float, float, float, float, float>(Bounce.easeIn);
                case "bounceout":
                    return new Func<float, float, float, float, float>(Bounce.easeOut);
                case "bounceinout":
                    return new Func<float, float, float, float, float>(Bounce.easeInOut);
                case "circularin":
                    return new Func<float, float, float, float, float>(Circular.easeIn);
                case "circularout":
                    return new Func<float, float, float, float, float>(Circular.easeOut);
                case "circularinout":
                    return new Func<float, float, float, float, float>(Circular.easeInOut);
                case "cubicin":
                    return new Func<float, float, float, float, float>(Cubic.easeIn);
                case "cubicout":
                    return new Func<float, float, float, float, float>(Cubic.easeOut);
                case "cubicinout":
                    return new Func<float, float, float, float, float>(Cubic.easeInOut);
                case "elasticin":
                    return new Func<float, float, float, float, float>(Elastic.easeIn);
                case "elasticout":
                    return new Func<float, float, float, float, float>(Elastic.easeOut);
                case "elasticinout":
                    return new Func<float, float, float, float, float>(Elastic.easeInOut);
                case "exponentialin":
                    return new Func<float, float, float, float, float>(Exponential.easeIn);
                case "exponentialout":
                    return new Func<float, float, float, float, float>(Exponential.easeOut);
                case "exponentialinout":
                    return new Func<float, float, float, float, float>(Exponential.easeInOut);
                case "quadraticin":
                    return new Func<float, float, float, float, float>(Quadratic.easeIn);
                case "quadraticout":
                    return new Func<float, float, float, float, float>(Quadratic.easeOut);
                case "quadraticinout":
                    return new Func<float, float, float, float, float>(Quadratic.easeInOut);
                case "quarticin":
                    return new Func<float, float, float, float, float>(Quartic.easeIn);
                case "quarticout":
                    return new Func<float, float, float, float, float>(Quartic.easeOut);
                case "quarticinout":
                    return new Func<float, float, float, float, float>(Quartic.easeInOut);
                case "quinticin":
                    return new Func<float, float, float, float, float>(Quintic.easeIn);
                case "quinticout":
                    return new Func<float, float, float, float, float>(Quintic.easeOut);
                case "quinticinout":
                    return new Func<float, float, float, float, float>(Quintic.easeInOut);
                case "sinein":
                    return new Func<float, float, float, float, float>(starLiGHT.ParticleSystem.Common.Sine.easeIn);
                case "sineout":
                    return new Func<float, float, float, float, float>(starLiGHT.ParticleSystem.Common.Sine.easeOut);
                case "sineinout":
                    return new Func<float, float, float, float, float>(starLiGHT.ParticleSystem.Common.Sine.easeInOut);
                default:
                    throw new Exception("unknown easing func: '" + name + "'");
            }
        }

        public static Func<float, float, float> getEnergyEasingFunc(string name)
        {
#if WINDOWS
            switch (name.ToLowerInvariant())
#else
            switch (name.ToLower())
#endif
            {
                case "linearnone":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Linear.easeNone);
                case "linearin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Linear.easeIn);
                case "linearout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Linear.easeOut);
                case "linearinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Linear.easeInOut);
                case "backin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Back.easeIn);
                case "backout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Back.easeOut);
                case "backinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Back.easeInOut);
                case "bouncein":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Bounce.easeIn);
                case "bounceout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Bounce.easeOut);
                case "bounceinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Bounce.easeInOut);
                case "circularin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Circular.easeIn);
                case "circularout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Circular.easeOut);
                case "circularinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Circular.easeInOut);
                case "cubicin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Cubic.easeIn);
                case "cubicout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Cubic.easeOut);
                case "cubicinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Cubic.easeInOut);
                case "elasticin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Elastic.easeIn);
                case "elasticout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Elastic.easeOut);
                case "elasticinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Elastic.easeInOut);
                case "exponentialin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Exponential.easeIn);
                case "exponentialout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Exponential.easeOut);
                case "exponentialinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Exponential.easeInOut);
                case "quadraticin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quadratic.easeIn);
                case "quadraticout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quadratic.easeOut);
                case "quadraticinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quadratic.easeInOut);
                case "quarticin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quartic.easeIn);
                case "quarticout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quartic.easeOut);
                case "quarticinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quartic.easeInOut);
                case "quinticin":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quintic.easeIn);
                case "quinticout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quintic.easeOut);
                case "quinticinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Quintic.easeInOut);
                case "sinein":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Sine.easeIn);
                case "sineout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Sine.easeOut);
                case "sineinout":
                    return new Func<float, float, float>(starLiGHT.ParticleSystem.Common.EnergyEasing.Sine.easeInOut);

                default:
                    throw new Exception("unknown easing func: '" + name + "'");
            }
        }
    }
}
